package zheezes.eisp.compute.model;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import org.apache.log4j.Logger;

import zheezes.eisp.data.orm.CalcTask;
import zheezes.eisp.data.orm.Concentrator;
import zheezes.eisp.data.orm.GroupPo;
import zheezes.eisp.data.orm.GroupStat;
import zheezes.eisp.data.orm.Summator;
import zheezes.eisp.data.orm.SummatorDailyFrozenData;


public class GroupStatCalcTaskHandler extends CalcTaskHandler {
	private final static Logger logger = Logger.getLogger(GroupStatCalcTaskHandler.class);
	
	public void run() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(task.getDate());
		if(calc(task.getTargetId(), cal) == 0) {
			task.setStatus(CalcTask.STATUS_FINISH);
			dataAccessor.updateCalcTask(task);
		}
	}

	private int calc(int id, Calendar cal) {
		try {
		List<GroupPo> notColledSubGroups = dataAccessor
				.queryNotCalcedSubGroupByIdAndDate(id, cal.getTime());
		logger.debug(String.format("there is %d sub_group to calc in %d", notColledSubGroups.size(), id));
		for (GroupPo gp : notColledSubGroups) {
			if(terminated || calc(gp.getId(), cal) != 0) {
				logger.debug(String.format("calc produce was terminated or calc sub_group %d failure", gp.getId()));
				return -1;
			}
		}
		GroupStat stat = new GroupStat();
		// init all values
		stat.setTermNum(0);
		stat.setInstalledTermNum(0);
		stat.setOnlineTermNum(0);
		// stat.setOfflineTermNum(0);
		// stat.setUserNum(0); // not to calc
		stat.setResMeterNum(0);
		stat.setColledResMeterNum(0);
		stat.setCutOffResMeterNum(0);
		stat.setSumUse(new BigDecimal(0));
		stat.setTotalProxValue(new BigDecimal(0));
		stat.setTotalCurValue(new BigDecimal(0));
		// finish to init all values
		List<GroupPo> subGroups = dataAccessor.querySubGroupById(id);
		List<Concentrator> cons = dataAccessor.queryConByGroupId(id);
		List<GroupStat> subGroupStats = dataAccessor.querySubGroupStatByIdAndDate(id, cal.getTime());
		if((subGroups == null) || (cons == null) || (subGroupStats == null)) {
			return -1;
		}
		stat.setGroupId(id);
		// sum group's statics
		for (GroupStat sst : subGroupStats) {
			if(terminated) {
				logger.info("terminated when traverse group statics");
				return -1;
			}
			stat.setTermNum(stat.getTermNum() + sst.getTermNum());
			stat.setInstalledTermNum(stat.getInstalledTermNum() + sst.getInstalledTermNum());
			stat.setOnlineTermNum(stat.getOnlineTermNum() + sst.getOnlineTermNum());
			// stat.setOfflineTermNum(stat.getOfflineTermNum() + st.getOfflineTermNum());
			// stat.setUserNum(stat.getUserNum() + sst.getUserNum());
			stat.setResMeterNum(stat.getResMeterNum() + sst.getResMeterNum());
			stat.setColledResMeterNum(stat.getColledResMeterNum() + sst.getColledResMeterNum());
			stat.setCutOffResMeterNum(stat.getCutOffResMeterNum() + sst.getCutOffResMeterNum());
			stat.setSumUse(stat.getSumUse().add(sst.getSumUse() != null ? sst.getSumUse() : new BigDecimal(0)));
			stat.setTotalProxValue(stat.getTotalProxValue().add(sst.getTotalProxValue() != null ? sst.getTotalProxValue() : new BigDecimal(0)));
			stat.setTotalCurValue(stat.getTotalCurValue().add(sst.getTotalCurValue() != null ? sst.getTotalCurValue() : new BigDecimal(0)));
			// stat.setTotalUse(stat.getTotalUse().add(sst.getTotalUse()));
		}
		stat.setTermNum(stat.getTermNum() + cons.size());
		for (Concentrator con : cons) {
			if(terminated) {
				logger.info("terminated when traverse concentrator statics");
				return -1;
			}
			int num;
			BigDecimal deci = null;
			
			// stat.setTermNum(stat.getTermNum() + 1);
			if(con.getInstallDate() != null || con.getInstallAddr() != null) {
				stat.setInstalledTermNum(stat.getInstalledTermNum() + 1);
			}
			if(dataAccessor.isOnline(con.getLogicAddr())) {
				stat.setOnlineTermNum(stat.getOnlineTermNum() + 1);
			}
			if((num = dataAccessor.countResMeterByCon(con.getId())) < 0) {
				logger.info("count resident meter by concentrator failure");
				return -1;
			}
			stat.setResMeterNum(stat.getResMeterNum() + num);
			if((num = dataAccessor.countResMeterWithDailyFrznByCon(con.getId(), cal.getTime())) < 0) {
				logger.info("count resident meter with daily frozen data by concentrator failure");
				return -1;
			}
			stat.setColledResMeterNum(stat.getColledResMeterNum() + num);
			if((num = dataAccessor.countCutOffResMeterByCon(con.getId())) < 0) {
				logger.info("count cut-off resident meter by concentrator failure");
				return -1;
			}
			stat.setCutOffResMeterNum(stat.getCutOffResMeterNum() + num);
			
			deci = dataAccessor.sumResMeterDailyUseByCon(con.getId(), cal.getTime());
			stat.setSumUse(stat.getSumUse().add(deci != null ? deci : new BigDecimal(0)));
			
			Summator sm = dataAccessor.getSummatorByCon(con.getId());
			
			SummatorDailyFrozenData smpdf = null;
			SummatorDailyFrozenData smcdf = null;
			
			if(sm != null) {
				// deci = new BigDecimal(0);
				Calendar tcal = (Calendar) cal.clone();
				tcal.add(Calendar.DATE, -1);
				smpdf = dataAccessor.querySummatorDailyFrozenDataByMpIdAndDate(sm.getMpId(), tcal.getTime());
				smcdf = dataAccessor.querySummatorDailyFrozenDataByMpIdAndDate(sm.getMpId(), cal.getTime());
				if(smpdf != null && smpdf.getPp() != null) {
					stat.setTotalProxValue(stat.getTotalProxValue().add(smpdf.getPp()));
				}
				if(smcdf != null && smcdf.getPp() != null) {
					stat.setTotalCurValue(stat.getTotalCurValue().add(smcdf.getPp()));
				}
			}
		}
		stat.setDate(cal.getTime());
		return dataAccessor.replaceGroupStat(stat);
		} catch(Exception e) {
			logger.debug(e.getMessage(), e);
			return -1;
		}
	}
	
	public void desc() {
		SimpleDateFormat dfmt = new SimpleDateFormat("yyyy-MM-dd");
		logger.debug(String.format("task date = %s", dfmt.format(task.getDate())));
	}
}
